import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import { debounce } from "@/utils";
import { onBeforeUnmount, onMounted } from "vue";

let cameraOpt = {
  fov: 30,
  aspect: 1,
  near: 1,
  far: 5000,
};
let renderOpt = {
  alpha: true,
  antialias: true,
};
export default function useThree(
  el,
  opt = {
    cameraOpt,
    renderOpt,
    axes: 500,
  }
) {
  if (opt.cameraOpt) {
    for (let key in opt.cameraOpt) {
      cameraOpt[key] = opt.cameraOpt[key];
    }
  }
  if (opt.renderOpt) {
    for (let key in opt.renderOpt) {
      renderOpt[key] = opt.renderOpt[key];
    }
  }

  let render = null;
  let camera = null;
  let controls = null;
  let scene = new THREE.Scene();

  if (opt.axes) {
    scene.add(new THREE.AxesHelper(opt.axes));
  }

  function resize() {
    render.setSize(el.offsetWidth, el.offsetHeight); // 根据缩放的窗口重新设置画布的大小
    // 垂直相机宽高比
    camera.aspect = el.offsetWidth / el.offsetHeight;
    // 更新相机投影矩阵
    camera.updateProjectionMatrix();
  }
  let debResize = debounce(resize, 100);

  onMounted(() => {
    render = new THREE.WebGLRenderer(renderOpt);
    render.setSize(can.value.offsetWidth, can.value.offsetHeight);
    render.setPixelRatio(window.devicePixelRatio);

    camera = new THREE.PerspectiveCamera(
      cameraOpt.fov,
      cameraOpt.aspect,
      cameraOpt.near,
      cameraOpt.far
    );
    camera.lookAt(0, 0, 0);

    controls = new OrbitControls(camera, render.domElement);
    controls.addEventListener("change", () => {
      render.render(sense, camera);
    });

    el.appendChild(render.domElement);

    if (opt.aniFn && typeof opt.aniFn === "function") {
      opt.aniFn(); //动画渲染
    } else {
      render.render(sense, camera); //单次渲染
    }

    window.addEventListener("resize", debResize);
  });

  onBeforeUnmount(() => {
    window.removeEventListener("resize", debResize);
    render.dispose();
    controls = null;
    render = null;
    camera = null;
    scene = null;
  });

  return {
    render,
    camera,
    scene,
  };
}
